home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 12 / CU Amiga Magazine's Super CD-ROM 12 (1997)(EMAP Images)(GB)[!][issue 1997-07].iso / System / CDsupport / aMiPEG / source / ham8.c < prev    next >
C/C++ Source or Header  |  1997-02-06  |  10KB  |  406 lines

  1. /*
  2.  *  This source copes with all amiga-specific stuff as opening the screen, resizing
  3.  *  it using user copper lists, etc.
  4.  *
  5.  *  Copper-based resizing is now implemented, although no aspect ratio is taken care of.
  6.  *
  7.  *  HAM6 is supported now.
  8.  *
  9.  *  Michael Rausch  14-4-94  1:11:59
  10.  *
  11.  *  Some fixes to allow for non-default monitors
  12.  *
  13.  *  Miloslaw Smyk  21-2-96
  14.  */
  15.  
  16. #include <proto/exec.h>
  17. #include <proto/intuition.h>
  18. #include <proto/graphics.h>
  19. #include <proto/asl.h>
  20.  
  21. #include <libraries/asl.h>
  22. #include <exec/memory.h>
  23. #include <hardware/custom.h>
  24. #include <graphics/copper.h>
  25. #include <graphics/gfxbase.h>
  26. #include <graphics/gfxmacros.h>
  27. #include <graphics/videocontrol.h>
  28. #include <graphics/displayinfo.h>
  29. #include <graphics/display.h>
  30.  
  31. #include <dos/dos.h>
  32. #include <proto/dos.h>
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37.  
  38. #include "video.h"
  39. #include "proto.h"
  40. extern int ditherType;
  41.  
  42. extern void HAM8_Init(struct RastPort *);    // kinda static
  43. extern void HAM8_Init_lores(struct RastPort *);
  44. extern void HAM6_Init_lores(struct RastPort *);
  45.  
  46. void (*HAM8_draw)(void *, int, int);
  47.  
  48.  
  49. #define custom ((*(volatile struct Custom *)(0xdff000)))
  50.  
  51.  
  52. struct IntuitionBase *IntuitionBase;
  53. /* struct GfxBase *GfxBase; */
  54. extern struct ExecBase *SysBase;
  55. static struct Screen *screen;
  56. static ULONG soerror = NULL;
  57.  
  58. int gfxver;
  59. ULONG *kaiko = NULL;
  60.  
  61. int lores=TRUE, sdbl=TRUE, ham6=FALSE;
  62.  
  63. int max_x, max_y;
  64.  
  65. static struct ColorSpec firstblack[2]={ {0,0,0,0}, {-1, 0,0,0} };    /* Color 0 is 0x000*/
  66.  
  67.  
  68. static void Quit(char *why, int failcode)
  69. {
  70.     puts(why);
  71.     exit(failcode);
  72. }
  73.  
  74. static void output_term(void)
  75. {
  76.     close_timer();
  77.  
  78.     if (screen)
  79.     {
  80.         FreeVPortCopLists(&(screen->ViewPort));
  81.         RemakeDisplay();
  82.         CloseScreen(screen);
  83.     }
  84.     if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
  85.     if (GfxBase) CloseLibrary((struct Library *) GfxBase);
  86. }
  87.  
  88.  
  89. int get_ham_modeid(void)
  90. {
  91.     struct ScreenModeRequester *scrMdReq;
  92.     int modeid = 0xffffffff;
  93.  
  94.     if(scrMdReq = AllocAslRequestTags(ASL_ScreenModeRequest,
  95.                                                                         ASLSM_MinWidth, 200,
  96.                                                                         ASLSM_MinHeight, 200,
  97.                                                                         ASLSM_MinDepth, 6,
  98.                                                                         ASLSM_MaxDepth, 8,
  99.                                                                         ASLSM_PropertyFlags, DIPF_IS_HAM,
  100.                                                                         ASLSM_PropertyMask, DIPF_IS_HAM,
  101.                                                                         TAG_DONE))
  102.     {
  103.         if(AslRequestTags(scrMdReq, TAG_DONE))
  104.             modeid = scrMdReq->sm_DisplayID;
  105.  
  106.         FreeAslRequest(scrMdReq);
  107.     }
  108.  
  109.     return(modeid);
  110. }
  111.  
  112.  
  113. void InitColorDisplay(void)
  114. {
  115.     atexit(output_term);
  116.  
  117.     if ((GfxBase=(struct GfxBase *) OpenLibrary("graphics.library",37))==NULL)
  118.         Quit("graphics.library is too old, <V39",25);
  119.     if ((IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",37))==NULL)
  120.         Quit("intuition.library is too old, <V39",25);
  121.  
  122.     gfxver = GfxBase->LibNode.lib_Version;
  123.     if(gfxver>=40) kaiko = GfxBase->ChunkyToPlanarPtr;
  124.  
  125.     HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  126.     DoDitherImage = NoDitherImage;
  127.  
  128.     if((modeid == 0xffffffff) && ((modeid = get_ham_modeid()) == 0xffffffff))
  129.         Quit("aMiPEG: unable to open HAM display...", 25);
  130. }
  131.  
  132.  
  133. /*
  134.  *   Resize the display using a copper list. Nifty'n neat amiga feature.
  135.  *
  136.  *   Phew ... takes now 2 hours to fiddle the system-compliant custom modulo stuff.
  137.  */
  138. void ResizeDisplay(int w, int h)
  139. {
  140.     struct UCopList *ucoplist;
  141.     static struct TagItem uCopTags[] = {
  142.         { VC_NoColorPaletteLoad, TRUE },
  143.         { VTAG_USERCLIP_SET, NULL },
  144.         { VTAG_END_CM, NULL }};
  145.     int i,j,k, y, fp_each, locallores;
  146.     struct CopList *dspins;
  147.     struct CopIns *copins;
  148.     short bpl1mod=-1, bpl2mod=-1, last1, last2, this1, this2;
  149.     ULONG id;
  150.     struct DimensionInfo dim_info;
  151.     BOOL quit = FALSE;
  152.     struct IntuiMessage *msg;
  153.     static char win_title[256];
  154.  
  155.     if(ditherType == NO_DITHER) return;
  156.  
  157.     if(ditherType == CYBERGFX_DITHER || ditherType == CYBERGFXGRAY_DITHER || ditherType == GRAY_DITHER)
  158.     {
  159.         ModifyIDCMP(cyber_window, IDCMP_NEWSIZE);
  160.  
  161.         SizeWindow(cyber_window, w - 160, h - 120);
  162.  
  163.         sprintf(win_title, "%s [%dx%d]", FilePart(animname), w, h);
  164.         SetWindowTitles(cyber_window, win_title, (UBYTE *)~0);
  165.  
  166.         while(!quit)
  167.         {
  168.             WaitPort(cyber_window->UserPort);
  169.             while(msg = (struct IntuiMessage *)GetMsg(cyber_window->UserPort))
  170.             {
  171.                 if(msg->Class == IDCMP_NEWSIZE)
  172.                     quit = TRUE;
  173.  
  174.                 ReplyMsg((struct Message *)msg);
  175.             }
  176.         }
  177.  
  178.         ModifyIDCMP(cyber_window, CLOSEWINDOW | MOUSEBUTTONS);
  179.  
  180.         original_x = cyber_window->Width;
  181.         original_y = cyber_window->Height;
  182.         return;
  183.     }
  184.  
  185.     id = modeid & MONITOR_ID_MASK;
  186.  
  187.     if (GetDisplayInfoData(FindDisplayInfo(id), (UBYTE *)&dim_info, sizeof(struct DimensionInfo), DTAG_DIMS, 0))
  188.         max_y=dim_info.StdOScan.MaxY - dim_info.StdOScan.MinY + 1;
  189.     else
  190.         max_y=200;
  191.  
  192.     if(h>max_y)
  193.         sdbl=FALSE, max_y<<=1;
  194.  
  195.     if(!(GfxBase->ChipRevBits0 & (GFXF_AA_ALICE|GFXF_AA_LISA)))
  196.         ham6 = TRUE;
  197.  
  198.     if(ham6)
  199.         lores=TRUE;
  200.     locallores = lores && (w<=160);
  201.     max_x = (locallores ? 320 : 640);
  202.  
  203.     switch(id)
  204.     {
  205.         case A2024_MONITOR_ID:
  206.             Quit("Get some colors, dude.", 25);
  207.  
  208.         case DBLPAL_MONITOR_ID: /* ARGH!  Kick their butts for this one! */
  209.             if(sdbl)
  210.                 id = locallores ? DBLPALLORESHAMFF_KEY : DBLPALHIRESHAMFF_KEY;
  211.             else
  212.                 id = locallores ? DBLPALLORESHAM_KEY : DBLPALHIRESHAM_KEY;
  213.             break;
  214.  
  215.         case DBLNTSC_MONITOR_ID:
  216.             if(sdbl)
  217.                 id = locallores ? DBLNTSCLORESHAMFF_KEY : DBLNTSCHIRESHAMFF_KEY;
  218.             else
  219.                 id = locallores ? DBLNTSCLORESHAM_KEY : DBLNTSCHIRESHAM_KEY;
  220.             break;
  221.  
  222.         case EURO72_MONITOR_ID:
  223.             if(sdbl)
  224.                 id = locallores ? EURO72LORESHAMDBL_KEY : EURO72PRODUCTHAMDBL_KEY;
  225.             else
  226.                 id = locallores ? EURO72LORESHAM_KEY : EURO72PRODUCTHAM_KEY;
  227.             break;
  228.  
  229.         case VGA_MONITOR_ID:
  230.             if(sdbl)
  231.                 id = locallores ? VGALORESHAMDBL_KEY : VGAPRODUCTHAMDBL_KEY;
  232.             else
  233.                 id = locallores ? VGALORESHAM_KEY : VGAPRODUCTHAM_KEY;
  234.             break;
  235.  
  236.         case PAL_MONITOR_ID:
  237.         case NTSC_MONITOR_ID:
  238. /*
  239.             if(gfxver >= 40 && sdbl)
  240.                 id = locallores ? id | LORESHAMSDBL_KEY: id | HIRESHAMSDBL_KEY;
  241.             else
  242. */
  243.                 sdbl=FALSE, id = locallores ? id | HAM_KEY : id | HIRESHAM_KEY;
  244.             break;
  245.  
  246.         default:
  247.             printf("ModeID 0x%x either doesn't support HAM or is unknown to aMiPEG.", id);
  248.             Quit("", 10);
  249.     }
  250.  
  251.     if(!(screen=OpenScreenTags(NULL,
  252.         SA_DisplayID,    id,
  253.         SA_Depth,    ham6?6:8,
  254.         SA_Width,    max_x,
  255.         SA_Colors,    firstblack,
  256.         SA_Type,    CUSTOMSCREEN|SCREENQUIET,
  257.         SA_Quiet,     TRUE,
  258.         SA_Interleaved,    !ham6, //TRUE,
  259.         SA_Overscan,    OSCAN_STANDARD,
  260.         SA_MinimizeISG,    TRUE,
  261.         SA_ErrorCode,    &soerror,
  262.         TAG_END))) Quit("Couldn't open screen.",25);
  263.  
  264.     if((screen->RastPort.BitMap->Depth == 6) && !ham6)
  265.         Quit("Incorrect depth. Please try to specify \"-dither ham6\" explicitely.",25);
  266.  
  267.     if(lores) {
  268.         if(ham6)
  269.         {    // the new ham6 routines do not handle interleaved bitmaps anymore
  270.             HAM6_Init_lores(&(screen->RastPort));
  271.             HAM8_draw = HAM6_draw_lores;
  272.             DoDitherImage = ColorDitherImage_12bit;
  273.         } else {
  274.             HAM8_Init_lores(&(screen->RastPort));
  275.             HAM8_draw = HAM8_draw_lores;
  276.             DoDitherImage = ColorDitherImage_lores;    // lacks kaiko support, actually
  277.         }
  278.         max_x >>=1;
  279.  
  280.     } else {
  281.         HAM8_Init(&(screen->RastPort));
  282.         HAM8_draw = HAM8_draw_hires;
  283.         DoDitherImage = ColorDitherImage;    // kaiko on one day
  284.         max_x >>=2;
  285.     }
  286.  
  287.     if(noDisplayFlag)
  288.         HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  289.  
  290.  
  291.     /* the memory is freed upon exit in output_term via FreeVPortCopLists */
  292.     if(!(ucoplist = AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR)))
  293.         Quit("No memory for copper list.",25);
  294.  
  295.     /* fiddle out some hardware values from this screen's init copper list */
  296.     dspins=screen->ViewPort.DspIns;
  297.     copins=dspins->CopIns;
  298.     for(i=dspins->Count-1; i>=0; i--, copins++)
  299.     {
  300.         j = copins->DESTDATA;
  301.  
  302.         switch(copins->DESTADDR & 0xfff)    // argh! kick 2.1 messes this up!
  303.         {        
  304.             case (int)&((*(struct Custom *)(0)).bpl1mod):
  305.                 last1=bpl1mod = j;
  306.                 break;
  307.             case (int)&((*(struct Custom *)(0)).bpl2mod):
  308.                 last2=bpl2mod = j;
  309.                 break;
  310.         }
  311.     }
  312.  
  313.     if(bpl1mod==-1 || bpl2mod==-1)
  314.     {
  315.         printf("ooops\n");
  316.         return;    /* hmmm? */
  317.     }
  318.  
  319.     if((bpl1mod == bpl2mod) && sdbl) sdbl=FALSE;
  320.  
  321.     y = screen->Height;
  322.     (void) CINIT(ucoplist, y*3);        /* ... instructions per line */
  323.  
  324.  
  325.     if(sdbl)
  326.     {
  327.         /*
  328.          *  We abuse some of AGA's features here; double-scanning is implemented
  329.          *  by applying bpl1mod to ALL planes on one line, bpl2mod on the next.
  330.          *  Obviously, double-scanning enables some kind of internal chipmem cache.
  331.          *  At least, it's faster. And (because of?) less copper instructions.
  332.          */
  333.  
  334.         fp_each = ((y*2)<<8) / (short)h;
  335.         for(k=fp_each, j=0; j<y; j++)                /* for each line in the display */
  336.         {
  337.  
  338.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  339.                 this1=bpl1mod;
  340.             else                        /* finally, we are ready; next one */
  341.                 this1=bpl2mod, k=(k&0xff)+fp_each;
  342.  
  343.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  344.                 this2=bpl1mod;
  345.             else                        /* finally, we are ready; next one */
  346.                 this2=bpl2mod, k=(k&0xff)+fp_each;
  347.  
  348.             if(last1!=this1 || last2!=this2)
  349.                 CWAIT(ucoplist, j, 0);
  350.  
  351.             if(last1!=this1)
  352.             {
  353.                 CMOVE(ucoplist, custom.bpl1mod, this1);
  354.                 last1=this1;
  355.             }
  356.  
  357.             if(last2!=this2)
  358.             {
  359.                 CMOVE(ucoplist, custom.bpl2mod, this2);
  360.                 last2=this2;
  361.             }
  362.         }
  363.     } else {
  364.         /*
  365.          *  No scan-doubling possible; most probably because of a pal/ntsc screen 
  366.          *  and no V40 graphics library available.
  367.          */
  368.  
  369.         bpl1mod -= screen->RastPort.BitMap->BytesPerRow;
  370.  
  371.         fp_each = (y<<8) / (short)h;
  372.         for(k=fp_each, j=0; j<y; j++)                /* for each line in the display */
  373.         {
  374.  
  375.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  376.                 this1=bpl1mod;
  377.             else                        /* finally, we are ready; next one */
  378.                 this1=bpl2mod, k=(k&0xff)+fp_each;
  379.  
  380.             if(last1!=this1)
  381.             {
  382.                 CWAIT(ucoplist, j, 0);
  383.                 CMOVE(ucoplist, custom.bpl1mod, this1);
  384.                 CMOVE(ucoplist, custom.bpl2mod, this1);
  385.                 last1=this1;
  386.             }
  387.         }
  388.     }
  389.  
  390.     /*
  391.      *  Pretty nifty, isn't it? Finally, even a little bit copper-list-optimizing is build in!
  392.      */
  393.  
  394.     CEND(ucoplist);
  395.  
  396.     /* Set the freshly created user copper list */
  397.     //Forbid();
  398.     screen->ViewPort.UCopIns = ucoplist;
  399.     //Permit();
  400.  
  401.     /*  Enable user copper list clipping for this ViewPort.  */
  402.     (void) VideoControl( screen->ViewPort.ColorMap, uCopTags );
  403.  
  404.     RethinkDisplay();
  405. }
  406.